﻿using FastORM.Entity;
using FastORM.Exception;
using FastUtil.Convert;
using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;

namespace FastORM.Mapping
{
    public class StructMapping
    {
        private static StructMapping Mapping = null;
        private static object Mapping_Lock = new object();
        private Dictionary<Type, MapperEntity> StructDic { set; get; }
        public static StructMapping GetInstance()
        {
            if (Mapping == null)
            {
                lock (Mapping_Lock)
                {
                    if (Mapping == null)
                    {
                        Mapping = new StructMapping();
                    }
                }
            }
            return Mapping;
        }
        public StructMapping()
        {
            this.ScanStruct();
        }


        public void ScanStruct()
        {
            if (StructDic == null)
            {
                StructDic = new Dictionary<Type, MapperEntity>();
            }
            Type BaseStrcutType = typeof(BaseEntity);
            var Assemblys = StructConvert.ConvertArrayToList(AppDomain.CurrentDomain.GetAssemblies());
            foreach (Assembly AssItem in Assemblys)
            {
                try
                {
                    List<Type> TypeList = StructConvert.ConvertArrayToList(AssItem.GetTypes()).FindAll((Type type) => BaseStrcutType.IsAssignableFrom(type) && type != BaseStrcutType);
                    foreach (Type TypeItem in TypeList)
                    {
                        MapperEntity Entity = new MapperEntity(TypeItem);
                        Entity.ScanSelf();
                        StructDic.Add(TypeItem, Entity);
                    }
                }
                catch (System.Exception)
                {

                }
            }
        }

        public MapperEntity GetMapperEntity(Type @Type)
        {
            //如果时动态加载dll，这里需要进行判断，没有进行重新生成
            if (!StructDic.ContainsKey(@Type))
            {
                MapperEntity Entity = new MapperEntity(@Type);
                Entity.ScanSelf();
                StructDic.Add(@Type, Entity);
            }
            return StructDic[@Type];
        }

        public T MapDataToEntity<T>(DataRow Row)
        {
            //如果时动态加载dll，这里需要进行判断，没有进行重新生成
            if (!StructDic.ContainsKey(typeof(T)))
            {
                MapperEntity Entity = new MapperEntity(typeof(T));
                Entity.ScanSelf();
                StructDic.Add(typeof(T), Entity);
            }
            return StructDic[typeof(T)].Map<T>(Row);
        }

        public List<ParamEntity> MapParams<T>(T Entity)
        {
            List<ParamEntity> ParamList = new List<ParamEntity>();
            MapperEntity Map = StructDic[typeof(T)];
            foreach (var item in Map.ColumnMapDic)
            {
                ParamEntity Param = new ParamEntity();
                Param.ParamName = item.Value;
                Param.ParamValue = Map.EmitDic[item.Key.Name].EmitGetter(Entity);
                ParamList.Add(Param);
            }
            return ParamList;
        }

        public List<ParamEntity> MapKeyParam<T>(string KeyFieldValue)
        {
            List<ParamEntity> ParamList = new List<ParamEntity>();
            MapperEntity Map = StructDic[typeof(T)];
            ParamEntity Param = new ParamEntity();
            Param.ParamName = Map.KeyName;
            Param.ParamValue = KeyFieldValue;
            ParamList.Add(Param);
            return ParamList;
        }

    }
}
